package com.nulldev.util.crypto.api3.encryptors.unsupported;

import java.nio.charset.Charset;

import com.nulldev.util.FinalBypass;
import com.nulldev.util.crypto.api2.Cryptable;
import com.nulldev.util.crypto.api2.EncryptionUtil;
import com.nulldev.util.crypto.api2.EncryptionUtil.Types;
import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.string.StringsUtil;

public class P2PX extends Cryptable{

	protected final Logger log = LoggerFactory.getLoggerName("com.nulldev.util.crypto.api3.encryptors.P2PX");
	public P2PX() {
		super("p2pX");
	}

	@Override
	public String encrypt(String object, String pass) {
		return this.encrypt(object, pass, null);
	}

	@Override
	public String encrypt(String object, String pass, Charset charset) {
		final String pass1 = StringsUtil.mul(object, pass);
		return pass1;
	}

	@Override
	public String decrypt(String object, String pass) {
		return this.decrypt(object, pass, null);
	}

	@Override
	public String decrypt(String object, String pass, Charset charset) {
		final String pass1 = StringsUtil.unmul(object, pass);
		return pass1;
	}

	@Override
	public String toPGPString(final String in) {
		final StringBuilder b = new StringBuilder();
		b.append("--START P2P BLOCK---").
			append(JVMUtil.lineSep()).
			append("Type: X-LIST").
			append(JVMUtil.lineSep()).
			append("Iterations: 1").
			append(JVMUtil.lineSep()).
			append("Data: {" + StringsUtil.toIDL(in) + "}").
			append(JVMUtil.lineSep()).
			append("----END P2P BLOCK---");
		return b.toString();
	}
	
	@Override
	public String toPGPString(final String in, final String key) {
		final StringBuilder b = new StringBuilder();
		b.append("--START P2P BLOCK---").
			append(JVMUtil.lineSep()).
			append("Type: X-LIST").
			append(JVMUtil.lineSep()).
			append("Iterations: 1").
			append(JVMUtil.lineSep()).
			append("Key: {" + key + "}").
			append(JVMUtil.lineSep()).
			append("Data: {" + StringsUtil.toIDL(in) + "}").
			append(JVMUtil.lineSep()).
			append("----END P2P BLOCK---");
		return b.toString();
	}
	
	@Override
	public String decryptFromPGP(final String in, final String key) {
		try {
			final FinalBypass<String> out = new FinalBypass<String>("default value");
			final String[] lines = StringsUtil.byLineSepeartor(in);
			boolean started = false;
			boolean ended = false;
			String pkey = key;
			String type = "";
			int iterations = -1;
			for (final String line : lines) {
				if (line.equals("--START P2P BLOCK---")) {
					started = true;
				}else if (line.equals("----END P2P BLOCK---")) {
					ended = true;
				}else if (line.startsWith("Iterations: ")){
					iterations = Integer.parseInt(line.substring(line.indexOf("Iterations: ") + 12));
				}else if (line.startsWith("Key: ")) {
					final String key_temp = StringsUtil.substringBetween(line, "Key: {", String.valueOf(line.charAt(line.length() - 1)));
					pkey = key_temp;
				}else if (line.startsWith("Type: ")) {
					type = line.substring(line.indexOf("Type: ") + 6);
					if (!type.equals("X-STANDARD") && !type.equals("X-LIST")) {
						throw new UnsupportedOperationException("Unsupported standard. (if not provided one, try 'X-STANDARD'.)");
					}
				}else if (line.startsWith("Data: {") && line.endsWith("}")) {
					if (iterations == -1) {
						this.log.warn("Iterations weren't provided, assuming that it's done once.");
						iterations = 1;
					}
					if (type.equals("X-STANDARD")) {
						final String o = EncryptionUtil.byType(Types.P2PX).decrypt(StringsUtil.fromIDL(StringsUtil.substringBetween(line, "Data: {", String.valueOf(line.charAt(line.length() - 1)))), pkey);
						out.setObject(o);
					}else if (type.equals("X-LIST")) {
						final String o = EncryptionUtil.byType(Types.P2PX).decrypt(StringsUtil.fromIDL(StringsUtil.substringBetween(line, "Data: {", String.valueOf(line.charAt(line.length() - 1)))), pkey);
						out.setObject(o);
					}
				}
			}
			return out.getObject();
		}catch (Exception e) {
			e.printStackTrace();
			return "error";
		}
	}
}
